////////////////////////////////////////////////////////////////////////////////////////////////////
// file:	D:\dev\wanton\Wanton\source\platform\mswin\mswinwindow.cpp
//
// summary:	Implements the mswinwindow class
//-----------------------------------------------------------------------------
// Copyright (c) 2013 Ash Matheson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////////////////////////

#include "pch.h"
#include "mswinwindow.h"
#include "Resource.h"

mswinwindow::mswinwindow(void)
	: m_hInst(0)
{
}

mswinwindow::~mswinwindow(void)
{
}

bool mswinwindow::Initialize()
{
	m_hInst = (HINSTANCE)GetModuleHandle(nullptr);

	LoadString(m_hInst, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(m_hInst, IDC_WANTON, szWindowClass, MAX_LOADSTRING);

	hAccelTable = LoadAccelerators(m_hInst, MAKEINTRESOURCE(IDC_WANTON));

	RegisterClass();

	// It's always a good idea (especially for later, when we want to use QueryPerformanceCounter)
	// to set out main process 'handler' to be on CPU 0.
	SetThreadAffinityMask(GetCurrentThread(), 1);

	m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, m_hInst, this);

	if (!m_hWnd)
	{
		return FALSE;
	}

	ShowWindow(m_hWnd, SW_SHOWNORMAL);
	UpdateWindow(m_hWnd);

	m_IsRunning = true;

	return TRUE;
}

void mswinwindow::RegisterClass()
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= StaticWindowProc;
	wcex.cbClsExtra		= 0;
	// Now, one trick we want to use is to store the pointer to this mswindowwindow instance into the class
	// structure for this window.  Once we have that, the static WindowProc can be used to resolve the 'correct'
	// mswindowwindow instance's handler.
	// When we create the window in CreateWindow (previous method) we can simply pass in 'this' as the extra
	// data and resolve it as part of the static WndProc, to redirect the messages to the appropriate windows.
	// Remember that we would need to virutalize WindowProc if we intend to subclass the mswindowwindow class.
	wcex.cbWndExtra		= sizeof(mswinwindow*);
	wcex.hInstance		= m_hInst;
	wcex.hIcon			= LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_WANTON));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WANTON);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SMALL));

	RegisterClassEx(&wcex);
}

bool mswinwindow::IsRunning()
{
	MSG msg;
	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return m_IsRunning;
}

LRESULT mswinwindow::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: Add any drawing code here...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		m_IsRunning = false;
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

LRESULT PASCAL mswinwindow::StaticWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_NCCREATE)
	{
		LPCREATESTRUCT cs = (LPCREATESTRUCT) lParam;
		SetWindowLongPtr(hWnd, GWL_USERDATA, (long) cs->lpCreateParams);
	}

	mswinwindow* window = (mswinwindow*) GetWindowLongPtr(hWnd, GWL_USERDATA);

	if (window != nullptr)
	{
		return window->WindowProc(hWnd, message, wParam, lParam);
	}
	else
	{
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
}